<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cesium Radar Effect</title>
    <style>
        html, body, #cesiumContainer {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.119/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.119/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
    Cesium.Ion.defaultAccessToken =
        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ZGRiMjUzZS1jZWNlLTRjMDYtODU5Mi05MjNiZDRjOGUwNTIiLCJpZCI6NDMxMDUsImlhdCI6MTY0NjI3MDQ2M30.ZH81WWILiz6RytEPHTdeRV-_Au5QuYN6JzJ8LsNqzLw'

    // 初始化Cesium Viewer
    const viewer = new Cesium.Viewer('cesiumContainer', {
        baseLayerPicker: false,
        animation: false,
        timeline: false,
        geocoder: false,
        homeButton: false,
        sceneModePicker: false,
        navigationHelpButton: false,
        fullscreenButton: false,
        infoBox: false,
        skyBox: false,
        skyAtmosphere: false
    })

    // 移除默认的实体
    viewer.entities.removeAll()

    // 创建雷达平面几何体
    const radarPrimitive = (() => {
        const radarPosition = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0) // 雷达位置

        // 雷达平面几何体
        const radarGeometry = new Cesium.PlaneGeometry({
            vertexFormat: Cesium.VertexFormat.POSITION_AND_ST,
            plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Z, 0.0),
            width: 2000.0,
            height: 2000.0
        })
        const circle = new Cesium.CircleGeometry({
            center: Cesium.Cartesian3.fromDegrees(116.39909886345453, 39.917349941511),
            radius: 100000.0
        })
        const circleGeometry = Cesium.CircleGeometry.createGeometry(circle)

        // 雷达材质
        const radarMaterial = new Cesium.Material({
            fabric: {
                type: 'RadarMaterial',
                uniforms: {
                    iTime: 0.0,
                    iResolution: new Cesium.Cartesian2(2000, 1900)
                },
                source: `
                    // 全局声明uniform变量
                    uniform float iTime;
                    uniform vec2 iResolution;

                    #define SMOOTH(r,R) (1.0-smoothstep(R-1.0,R+1.0, r))
                    #define RANGE(a,b,x) ( step(a,x)*(1.0-step(b,x)) )
                    #define RS(a,b,x) ( smoothstep(a-1.0,a+1.0,x)*(1.0-smoothstep(b-1.0,b+1.0,x)) )
                    #define M_PI 3.1415926535897932384626433832795

                    #define blue1 vec3(0.74,0.95,1.00)
                    #define blue2 vec3(0.87,0.98,1.00)
                    #define blue3 vec3(0.35,0.76,0.83)
                    #define blue4 vec3(0.953,0.969,0.89)
                    #define red   vec3(1.00,0.38,0.227)

                    #define MOV(a,b,c,d,t) (vec2(a*cos(t)+b*cos(0.1*(t)), c*sin(t)+d*cos(0.1*(t))))

                    // 辅助函数必须在主函数之前定义
                    float movingLine(vec2 uv, vec2 center, float radius) {
                        float theta0 = 90.0 * iTime;
                        vec2 d = uv - center;
                        float r = sqrt( dot( d, d ) );
                        if(r<radius) {
                            vec2 p = radius*vec2(cos(theta0*M_PI/180.0), -sin(theta0*M_PI/180.0));
                            float l = length( d - p*clamp( dot(d,p)/dot(p,p), 0.0, 1.0) );
                            d = normalize(d);
                            float theta = mod(180.0*atan(d.y,d.x)/M_PI+theta0,360.0);
                            float gradient = clamp(1.0-theta/90.0,0.0,1.0);
                            return SMOOTH(l,1.0)+0.5*gradient;
                        }
                        else return 0.0;
                    }

                    float circle(vec2 uv, vec2 center, float radius, float width) {
                        float r = length(uv - center);
                        return SMOOTH(r-width/2.0,radius)-SMOOTH(r+width/2.0,radius);
                    }

                    float circle2(vec2 uv, vec2 center, float radius, float width, float opening) {
                        vec2 d = uv - center;
                        float r = sqrt( dot( d, d ) );
                        d = normalize(d);
                        if( abs(d.y) > opening )
                            return SMOOTH(r-width/2.0,radius)-SMOOTH(r+width/2.0,radius);
                        else
                            return 0.0;
                    }

                    float circle3(vec2 uv, vec2 center, float radius, float width) {
                        vec2 d = uv - center;
                        float r = sqrt( dot( d, d ) );
                        d = normalize(d);
                        float theta = 180.0*(atan(d.y,d.x)/M_PI);
                        return smoothstep(2.0, 2.1, abs(mod(theta+2.0,45.0)-2.0)) *
                            mix( 0.5, 1.0, step(45.0, abs(mod(theta, 180.0)-90.0)) ) *
                            (SMOOTH(r-width/2.0,radius)-SMOOTH(r+width/2.0,radius));
                    }

                    float triangles(vec2 uv, vec2 center, float radius) {
                        vec2 d = uv - center;
                        return RS(-8.0, 0.0, d.x-radius) * (1.0-smoothstep( 7.0+d.x-radius,9.0+d.x-radius, abs(d.y)))
                            + RS( 0.0, 8.0, d.x+radius) * (1.0-smoothstep( 7.0-d.x-radius,9.0-d.x-radius, abs(d.y)))
                            + RS(-8.0, 0.0, d.y-radius) * (1.0-smoothstep( 7.0+d.y-radius,9.0+d.y-radius, abs(d.x)))
                            + RS( 0.0, 8.0, d.y+radius) * (1.0-smoothstep( 7.0-d.y-radius,9.0-d.y-radius, abs(d.x)));
                    }

                    float _cross(vec2 uv, vec2 center, float radius) {
                        vec2 d = uv - center;
                        int x = int(d.x);
                        int y = int(d.y);
                        float r = sqrt( dot( d, d ) );
                        if( (r<radius) && ( (x==y) || (x==-y) ) )
                            return 1.0;
                        else return 0.0;
                    }

                    float bip1(vec2 uv, vec2 center) {
                        return SMOOTH(length(uv - center),3.0);
                    }

                    float bip2(vec2 uv, vec2 center) {
                        float r = length(uv - center);
                        float R = 8.0+mod(87.0*iTime, 80.0);
                        return (0.5-0.5*cos(30.0*iTime)) * SMOOTH(r,5.0)
                            + SMOOTH(6.0,r)-SMOOTH(8.0,r)
                            + smoothstep(max(8.0,R-20.0),R,r)-SMOOTH(R,r);
                    }

                    vec4 computeColor(vec2 uv) {
                        vec3 finalColor;
                        vec2 c = iResolution * 0.5;

                        finalColor = vec3( 0.3*_cross(uv, c, 240.0) );
                        finalColor += ( circle(uv, c, 100.0, 1.0) + circle(uv, c, 165.0, 1.0) ) * blue1;
                        finalColor += circle(uv, c, 240.0, 2.0);
                        finalColor += circle3(uv, c, 313.0, 4.0) * blue1;
                        finalColor += triangles(uv, c, 315.0 + 30.0*sin(iTime)) * blue2;
                        finalColor += movingLine(uv, c, 240.0) * blue3;
                        finalColor += circle(uv, c, 10.0, 1.0) * blue3;
                        finalColor += 0.7 * circle2(uv, c, 262.0, 1.0, 0.5+0.2*cos(iTime)) * blue3;

                        if( length(uv-c) < 240.0 ) {
                            vec2 p = 130.0*MOV(1.3,1.0,1.0,1.4,3.0+0.1*iTime);
                            finalColor += bip1(uv, c+p) * vec3(1,1,1);
                            p = 130.0*MOV(0.9,-1.1,1.7,0.8,-2.0+sin(0.1*iTime)+0.15*iTime);
                            finalColor += bip1(uv, c+p) * vec3(1,1,1);
                            p = 50.0*MOV(1.54,1.7,1.37,1.8,sin(0.1*iTime+7.0)+0.2*iTime);
                            finalColor += bip2(uv,c+p) * red;
                        }

                        return vec4(finalColor, 1.0);
                    }

                    czm_material czm_getMaterial(czm_materialInput materialInput) {
                        czm_material material = czm_getDefaultMaterial(materialInput);
                        vec2 st = materialInput.st;
                        // 翻转Y轴以匹配Three.js坐标系
                        vec2 uv = vec2(st.x * iResolution.x, (1.0 - st.y) * iResolution.y);
                        vec4 color = computeColor(uv);
                        material.diffuse = color.rgb;
                        material.alpha = color.a;
                        return material;
                    }
                `
            },
            translucent: true
        })

        // 创建雷达图元
        return viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
                geometry: circleGeometry,
                // modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(radarPosition),
                attributes: {
                    color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                        new Cesium.Color(1.0, 1.0, 1.0, 1.0)
                    )
                }
            }),
            appearance: new Cesium.MaterialAppearance({
                material: radarMaterial,
                translucent: true,
                flat: true
            })
        }))
    })()

    /**
     * 创建一个点
     */
        // viewer.entities.add({
        //     position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
        //     point: {
        //         pixelSize: 10,
        //         color: Cesium.Color.RED
        //     }
        // })
        // 创建一个点实体，用entity
    const point1 = viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(116.39909886345453, 39.917349941511, 0),
                point: {
                    pixelSize: 10,
                    color: Cesium.Color.RED
                }
            }
        )
    // viewer.zoomTo(point1)
    // 设置相机位置
    viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(116.39909886345453, 39.917349941511, 200000),
        orientation: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(-90),
            roll: 0.0
        }
    })
    // 更新时间Uniform
    viewer.scene.preUpdate.addEventListener(function(scene, time) {
        const primitive = radarPrimitive
        if(primitive && primitive.appearance && primitive.appearance.material) {
            primitive.appearance.material.uniforms.iTime += 0.01
        }
    })
</script>
</body>
</html>
